home *** CD-ROM | disk | FTP | other *** search
/ Developer CD Series 1996 April: Mac OS SDK / Dev.CD Apr 96 SDK / Dev.CD Apr 96 SDK1.toast / Development Kits (Disc 1) / OpenDoc Development Framework / ODFDev / ODF / Examples / Draw / Sources / DrawLink.cpp < prev    next >
Encoding:
Text File  |  1995-11-08  |  36.1 KB  |  1,048 lines  |  [TEXT/MPS ]

  1. //========================================================================================
  2. //
  3. //    File:                DrawLink.cpp
  4. //    Release Version:    $ 1.0d11 $
  5. //
  6. //    Author:                Henri Lamiraux
  7. //    Linking added by:    M.Boetcher
  8. //
  9. //    Copyright:    © 1993, 1995 by Apple Computer, Inc., all rights reserved.
  10. //
  11. //========================================================================================
  12.  
  13. #include "ODFDraw.hpp"
  14.  
  15. #ifndef DRAWLINK_H
  16. #include "DrawLink.h"
  17. #endif
  18.  
  19. #ifndef DRAWDEF_H
  20. #include "DrawDef.h"
  21. #endif
  22.  
  23. #ifndef DRAWPART_H
  24. #include "DrawPart.h"
  25. #endif
  26.  
  27. #ifndef DRAWSEL_H
  28. #include "DrawSel.h"
  29. #endif
  30.  
  31. #ifndef BASESHP_H
  32. #include "BaseShp.h"
  33. #endif
  34.  
  35. #ifndef BOUNDSHP_H
  36. #include "BoundShp.h"
  37. #endif
  38.  
  39. #ifndef LINESHP_H
  40. #include "LineShp.h"
  41. #endif
  42.  
  43. #ifndef OVALSHP_H
  44. #include "OvalShp.h"
  45. #endif
  46.  
  47. #ifndef RECTSHP_H
  48. #include "RectShp.h"
  49. #endif
  50.  
  51. #ifndef RRECTSHP_H
  52. #include "RRectShp.h"
  53. #endif
  54.  
  55. #ifndef TEXTSHP_H
  56. #include "TextShp.h"
  57. #endif
  58.  
  59. #ifndef DRAWPRXY_H
  60. #include "DrawPrxy.h"
  61. #endif
  62.  
  63. // ----- Framework Includes -----
  64.  
  65. #ifndef FWFRAME_H
  66. #include "FWFrame.h"
  67. #endif
  68.  
  69. #ifndef FWITERS_H
  70. #include "FWIters.h"
  71. #endif
  72.  
  73. #ifndef FWPRTITE_H
  74. #include "FWPrtIte.h"
  75. #endif
  76.  
  77. #ifndef FWPRESEN_H
  78. #include "FWPresen.h"
  79. #endif
  80.  
  81. #ifndef FWPXYFRM_H
  82. #include "FWPxyFrm.h"
  83. #endif
  84.  
  85. #ifndef FWUTIL_H
  86. #include "FWUtil.h"
  87. #endif
  88.  
  89. #ifndef FWCLNINF_H
  90. #include "FWClnInf.h"
  91. #endif
  92.  
  93. #ifndef FWBARRAY_H
  94. #include "FWBArray.h"
  95. #endif
  96.  
  97. // ----- Foundation Includes -----
  98.  
  99. #ifndef FWORDCOL_H
  100. #include "FWOrdCol.h"
  101. #endif
  102.  
  103. #ifndef FWMEMMGR_H
  104. #include "FWMemMgr.h"
  105. #endif
  106.  
  107. // ----- OpenDoc Includes -----
  108.  
  109. #ifndef SOM_Module_OpenDoc_StdProps_defined
  110. #include <StdProps.xh>
  111. #endif
  112.  
  113. #ifndef SOM_Module_OpenDoc_StdTypes_defined
  114. #include <StdTypes.xh>
  115. #endif
  116.  
  117. #ifndef SOM_ODStorageUnit_xh
  118. #include <StorageU.xh>
  119. #endif
  120.  
  121. #ifndef SOM_ODUndo_xh
  122. #include <Undo.xh>
  123. #endif
  124.  
  125. #ifndef SOM_ODSession_xh
  126. #include <ODSessn.xh>
  127. #endif
  128.  
  129. #ifndef SOM_ODLink_xh
  130. #include <Link.xh>
  131. #endif
  132.  
  133. #ifndef SOM_ODLinkSpec_xh
  134. #include <LinkSpec.xh>
  135. #endif
  136.  
  137. #ifndef SOM_ODLinkSource_xh
  138. #include <LinkSrc.xh>
  139. #endif
  140.  
  141. //========================================================================================
  142. // Runtime Information
  143. //========================================================================================
  144.  
  145. FW_DEFINE_CLASS_M1(CDrawPublishLink, FW_CPublishLink)
  146. FW_DEFINE_CLASS_M1(CDrawSubscribeLink, FW_CSubscribeLink)
  147.  
  148. #ifdef FW_BUILD_MAC
  149. #pragma segment odfdraw
  150. #endif
  151.  
  152. //========================================================================================
  153. // Constants
  154. //========================================================================================
  155.  
  156. const ODPropertyName kDrawPropSourceLink = "ODFDraw:Property:SourceLink";
  157. const ODPropertyName kDrawPropDestLink   = "ODFDraw:Property:DestLink";
  158.  
  159. const ODValueType kDrawLinkValue = "ODFDraw:Value";
  160.  
  161. //========================================================================================
  162. //    class CDrawPublishLink
  163. //========================================================================================
  164.  
  165. //----------------------------------------------------------------------------------------
  166. //    CDrawPublishLink::CDrawPublishLink
  167. //----------------------------------------------------------------------------------------
  168.  
  169. CDrawPublishLink::CDrawPublishLink(Environment *ev, ODUpdateID updateID, 
  170.                                    FW_CPresentation* presentation, 
  171.                                    CDrawSelection* drawSelection,
  172.                                    FW_Boolean saveSelection) :
  173.     FW_CPublishLink(ev, updateID, presentation),
  174.     fDrawSelection(drawSelection),
  175.     fCollection(NULL),
  176.     fSavedSelection(NULL)
  177. {
  178.     //---- Create a new collection to hold the shapes in this link source ----
  179.     fCollection = new FW_CPrivOrderedCollection;
  180.  
  181.     //---- Save the selected shapes ----
  182.     if (saveSelection)
  183.     {
  184.         FW_COrderedCollectionIterator ite(fDrawSelection->GetSelectionCollection());
  185.         for (CBaseShape* shape = (CBaseShape*)ite.First(); ite.IsNotComplete(); shape = (CBaseShape*)ite.Next())
  186.         {
  187.             fCollection->AddLast(shape);
  188.         }
  189.     }
  190. }
  191.  
  192. //----------------------------------------------------------------------------------------
  193. //    CDrawPublishLink::~CDrawPublishLink
  194. //----------------------------------------------------------------------------------------
  195.  
  196. CDrawPublishLink::~CDrawPublishLink()
  197. {
  198.     delete fCollection;
  199. }
  200.  
  201. //----------------------------------------------------------------------------------------
  202. //    CDrawPublishLink::Publish - Override
  203. //----------------------------------------------------------------------------------------
  204.  
  205. void CDrawPublishLink::Publish(Environment* ev)
  206. {
  207.     //---- Mark the collected shapes as published
  208.     FW_COrderedCollectionIterator ite(fCollection);
  209.     for (CBaseShape* shape = (CBaseShape*)ite.First(); ite.IsNotComplete(); shape = (CBaseShape*)ite.Next())
  210.     {
  211.         shape->SetPublishLink(ev, this);
  212.     }
  213.  
  214.     //--- Force the first update using a new change ID
  215.     ODUpdateID change = fPresentation->GetPart(ev)->GetSession(ev)->UniqueUpdateID(ev);
  216.     this->ContentUpdated(ev, change, TRUE);    
  217. }
  218.  
  219. //----------------------------------------------------------------------------------------
  220. //    CDrawPublishLink::GetPublishFormat - Override
  221. //----------------------------------------------------------------------------------------
  222.  
  223. ODValueType CDrawPublishLink::GetPublishFormat(Environment* ev)
  224. {    
  225.     return kPublishFormat;
  226. }
  227.  
  228. //----------------------------------------------------------------------------------------
  229. //    CDrawPublishLink::ExternalizeLinkContent - Override
  230. //----------------------------------------------------------------------------------------
  231.  
  232. void CDrawPublishLink::ExternalizeLinkContent(Environment* ev, ODStorageUnit* linkSU)
  233. {    
  234.     // Remove extra properties (ODLinkSource::Clear removed only the content property)
  235.     FW_SURemoveProperty(ev, linkSU, kODPropContentFrame);
  236.  
  237.     // -- Pick a frame, any frame --
  238.     FW_CPresentationFrameIterator piter(fPresentation);
  239.     FW_CFrame* frame = piter.First();
  240.     FW_ASSERT(frame);
  241.  
  242.     // Since ExternalizeData writes the current selection,
  243.     // we need to temporarily select the shapes to be published
  244.     this->SelectShapes(ev);
  245.  
  246.     fDrawSelection->ExternalizeData(ev, frame, FW_kLinkStorage, linkSU, kODCloneToLink);
  247.  
  248.     // Now restore the saved selection
  249.     this->RestoreDrawSelection(ev);
  250. }
  251.  
  252. //----------------------------------------------------------------------------------------
  253. //    CDrawPublishLink::SelectShapes
  254. //----------------------------------------------------------------------------------------
  255. void CDrawPublishLink::SelectShapes(Environment* ev)
  256. {
  257.     // Save the list of selected shapes
  258.     fSavedSelection = fDrawSelection->GetSelectionCollection();
  259.     fDrawSelection->CloseSelection(ev);    // empty the selection
  260.  
  261.     // Add all our published shapes to the selection
  262.     FW_COrderedCollectionIterator iter(fCollection);
  263.     for (CBaseShape* shape = (CBaseShape*)iter.First(); iter.IsNotComplete(); shape = (CBaseShape*)iter.Next())
  264.     {
  265.         fDrawSelection->AddToSelection(ev, shape, FALSE);
  266.     }
  267. }
  268.  
  269. //----------------------------------------------------------------------------------------
  270. //    CDrawPublishLink::RestoreDrawSelection
  271. //----------------------------------------------------------------------------------------
  272. void CDrawPublishLink::RestoreDrawSelection(Environment* ev)
  273. {
  274.     fDrawSelection->CloseSelection(ev);    // empty the selection
  275.  
  276.     // Add the saved shapes to the selection
  277.     FW_COrderedCollectionIterator iter(fSavedSelection);
  278.     for (CBaseShape* shape = (CBaseShape*)iter.First(); iter.IsNotComplete(); shape = (CBaseShape*)iter.Next())
  279.     {
  280.         fDrawSelection->AddToSelection(ev, shape, FALSE);
  281.     }
  282.     fSavedSelection = NULL;
  283.  
  284.     // Redraw???
  285.     fPresentation->Invalidate(ev);    // force all frames to be redrawn
  286. }
  287.  
  288. //----------------------------------------------------------------------------------------
  289. //    CDrawPublishLink::HasEmbeddedFrame
  290. //----------------------------------------------------------------------------------------
  291. FW_Boolean CDrawPublishLink::HasEmbeddedFrame(Environment *ev, ODFrame* odFrame)
  292. {
  293.     // Is odFrame involved in this link source? (called by DoUpdateLinks)
  294.  
  295.     // --- Find out whether odFrame is involved in any link source ---
  296.     if (odFrame->GetLinkStatus(ev) == kODInLinkSource)
  297.     {
  298.         // -- Find out whether odFrame is one of my frames --
  299.         FW_CFrame* fwFrame = FW_CFrame::ODtoFWFrame(ev, odFrame);
  300.         if (fwFrame)
  301.         {
  302.             FW_COrderedCollectionIterator iter(fCollection);
  303.             for (CBaseShape* shape = (CBaseShape*)iter.First(); iter.IsNotComplete(); shape = (CBaseShape*)iter.Next())
  304.             {
  305.                 if ((shape->GetShapeType() == kProxyShape) && (((CProxyShape*)shape)->IsEmbeddedFrame(ev, odFrame)))
  306.                     return TRUE;
  307.             }
  308.         }
  309.     }
  310.  
  311.     return FALSE;
  312. }
  313.  
  314. //----------------------------------------------------------------------------------------
  315. //    CDrawPublishLink::GetFrameToRevealLink
  316. //----------------------------------------------------------------------------------------
  317. FW_CFrame* CDrawPublishLink::GetFrameToRevealLink(Environment* ev)
  318. {
  319.     // Just return the presentation's first display frame
  320.     FW_CPresentationFrameIterator piter(fPresentation);
  321.     return piter.First();
  322. }
  323.  
  324. //----------------------------------------------------------------------------------------
  325. //    CDrawPublishLink::DoSelect
  326. //----------------------------------------------------------------------------------------
  327. void CDrawPublishLink::DoSelect(Environment* ev, FW_CFrame* /*frame*/)
  328. {
  329.     fDrawSelection->CloseSelection(ev);    // empty the selection
  330.  
  331.     // Add all our published shapes to the selection
  332.     FW_COrderedCollectionIterator iter(fCollection);
  333.     for (CBaseShape* shape = (CBaseShape*)iter.First(); iter.IsNotComplete(); shape = (CBaseShape*)iter.Next())
  334.     {
  335.         fDrawSelection->AddToSelection(ev, shape, TRUE);    // draw selection handles
  336.     }
  337. }
  338.  
  339. //----------------------------------------------------------------------------------------
  340. //    CDrawPublishLink::AddShape
  341. //----------------------------------------------------------------------------------------
  342. void CDrawPublishLink::AddShape(Environment* ev, CBaseShape* shape)
  343. {
  344.     shape->SetPublishLink(ev, this);
  345.     fCollection->AddLast(shape);
  346. }
  347.  
  348. //----------------------------------------------------------------------------------------
  349. //    CDrawPublishLink::Externalize
  350. //----------------------------------------------------------------------------------------
  351.  
  352. void CDrawPublishLink::Externalize(Environment* ev, ODStorageUnit* storageUnit,
  353.                                    FW_CCloneInfo* cloneInfo)
  354. {
  355.     //-- Storage unit must be focussed to property kDrawPropDestLink, value drawPartValueType
  356.     fODLinkSource->Externalize(ev);
  357.  
  358.     ODID linkID = fODLinkSource->GetID(ev);
  359.     if (cloneInfo != NULL)
  360.     {
  361.         linkID = cloneInfo->Clone(ev, linkID, 0, 0);
  362.     }
  363.     FW_ASSERT(linkID != kODNULL);
  364.  
  365.     //--- Write a reference to the link ---
  366.     ODStorageUnitRef suRef;
  367.     storageUnit->GetStrongStorageUnitRef(ev, linkID, suRef);
  368.     FW_CByteArray byteArray(&suRef, sizeof(ODStorageUnitRef));
  369.     storageUnit->SetValue(ev, byteArray);
  370.  
  371.     //--- Write update ID ---
  372.     byteArray.Set(&fUpdateID, sizeof(ODUpdateID));
  373.     storageUnit->SetValue(ev, byteArray);
  374.  
  375.     //--- Write the number of shapes in the link ---
  376.     unsigned long shapeCount = fCollection->Count();
  377.     FW_ASSERT(shapeCount != 0);
  378.     byteArray.Set(&shapeCount, sizeof(unsigned long));
  379.     storageUnit->SetValue(ev, byteArray);
  380.  
  381.     //--- Write the externalization index for each shape in the link ---
  382.     FW_COrderedCollectionIterator iter(fCollection);
  383.     for (CBaseShape* shape = (CBaseShape*)iter.First(); iter.IsNotComplete(); shape = (CBaseShape*)iter.Next())
  384.     {
  385.         short extIndex = shape->GetExternalizationIndex();
  386.         byteArray.Set(&extIndex, sizeof(short));
  387.         storageUnit->SetValue(ev, byteArray);
  388.     }
  389. }
  390.  
  391. //========================================================================================
  392. //    class CDrawSubscribeLink
  393. //========================================================================================
  394.  
  395. //----------------------------------------------------------------------------------------
  396. //    CDrawSubscribeLink::CDrawSubscribeLink
  397. //----------------------------------------------------------------------------------------
  398.  
  399. CDrawSubscribeLink::CDrawSubscribeLink(Environment* ev, ODLink* odLink, 
  400.                                         FW_CPresentation* presentation, 
  401.                                         CDrawSelection* drawSelection,
  402.                                         ODLinkInfo* linkInfo) :
  403.     FW_CSubscribeLink(ev, odLink, linkInfo, presentation),
  404.     fDrawSelection(drawSelection),
  405.     fCollection(NULL),
  406.     fSavedSelection(NULL)
  407. {
  408.     fUpdateOffset.Clear();
  409. }
  410.  
  411. //----------------------------------------------------------------------------------------
  412. //    CDrawSubscribeLink::~CDrawSubscribeLink
  413. //----------------------------------------------------------------------------------------
  414.  
  415. CDrawSubscribeLink::~CDrawSubscribeLink()
  416. {
  417.     delete fCollection;
  418. }
  419.  
  420. //---------------------------------------------------------------------------------------
  421. //    CDrawSubscribeLink::Subscribe - Override
  422. //---------------------------------------------------------------------------------------
  423.  
  424. void CDrawSubscribeLink::Subscribe(Environment* ev)
  425. {
  426.     // SetCollection already initialized fCollection (called from DoUpdateLink)
  427. }
  428.  
  429. //---------------------------------------------------------------------------------------
  430. //    CDrawSubscribeLink::DoUpdateLink - Override
  431. //---------------------------------------------------------------------------------------
  432.  
  433. void CDrawSubscribeLink::DoUpdateLink(Environment* ev, ODStorageUnit* linkContentSU)
  434. {
  435.     // Read data from the linkContentSU
  436.     FW_CPresentationFrameIterator piter(fPresentation);
  437.     FW_CFrame* frame = piter.First();
  438.     FW_ASSERT(frame);
  439.  
  440.     // Since InternalizeData reads into the current selection,
  441.     // we need to save the selection and clear the linked shapes before reading new ones
  442.     this->SaveAndSelectShapes(ev);
  443.  
  444.     fDrawSelection->InternalizeData(ev, frame, linkContentSU, kODCloneFromLink);
  445.     this->SetCollection(ev);
  446.  
  447.     // Now restore the saved selection
  448.     this->RestoreDrawSelection(ev);
  449.  
  450.     fPresentation->Invalidate(ev);    // force all frames to be redrawn
  451. }
  452.  
  453. //----------------------------------------------------------------------------------------
  454. //    CDrawSubscribeLink::SetCollection
  455. //----------------------------------------------------------------------------------------
  456. void CDrawSubscribeLink::SetCollection(Environment *ev)
  457. {
  458.     FW_Boolean updating = (fCollection != NULL);
  459.     if (fCollection)
  460.         this->EmptyCollection(ev);
  461.     else
  462.         fCollection = new FW_CPrivOrderedCollection;
  463.         
  464.     FW_COrderedCollectionIterator ite(fDrawSelection->GetSelectionCollection());
  465.     for (CBaseShape *shape = (CBaseShape*)ite.First(); ite.IsNotComplete(); shape = (CBaseShape*)ite.Next())
  466.     {
  467.         shape->SetSubscribeLink(ev, this);
  468.         fCollection->AddLast(shape);
  469.     }
  470.  
  471.     if (updating && fUpdateOffset != FW_kZeroPoint)    // updating an existing link 
  472.     {
  473.         // move the updated shapes to their proper position
  474.         FW_CRect selRect;
  475.         fDrawSelection->GetDragRect(selRect);
  476.         fDrawSelection->OffsetSelection(ev, fUpdateOffset.x - selRect.left, fUpdateOffset.y - selRect.top);
  477.     }
  478. }
  479.  
  480. //----------------------------------------------------------------------------------------
  481. //    CDrawSubscribeLink::SelectShapes
  482. //----------------------------------------------------------------------------------------
  483. void CDrawSubscribeLink::SelectShapes(Environment* ev)
  484. {
  485.     fDrawSelection->CloseSelection(ev);    // empty the selection
  486.  
  487.     // Add all our subscribed shapes to the selection
  488.     FW_COrderedCollectionIterator iter(fCollection);
  489.     for (CBaseShape* shape = (CBaseShape*)iter.First(); iter.IsNotComplete(); shape = (CBaseShape*)iter.Next())
  490.     {
  491.         fDrawSelection->AddToSelection(ev, shape, FALSE);
  492.     }
  493. }
  494.  
  495. //----------------------------------------------------------------------------------------
  496. //    CDrawSubscribeLink::SaveAndSelectShapes
  497. //----------------------------------------------------------------------------------------
  498. void CDrawSubscribeLink::SaveAndSelectShapes(Environment* ev)
  499. {
  500.     // Save the list of selected shapes
  501.     fSavedSelection = fDrawSelection->GetSelectionCollection();
  502.     fDrawSelection->CloseSelection(ev);    // empty the selection
  503.  
  504.     if (!fCollection) return;    // fCollection is NULL when it's the first update
  505.  
  506.     // Add all our subscribed shapes to the selection so we can delete them
  507.     FW_COrderedCollectionIterator iter(fCollection);
  508.     for (CBaseShape* shape = (CBaseShape*)iter.First(); iter.IsNotComplete(); shape = (CBaseShape*)iter.Next())
  509.     {
  510.         fDrawSelection->AddToSelection(ev, shape, FALSE);
  511.     }
  512.  
  513.     // Save the selection's position
  514.     FW_CRect tempRect;
  515.     fDrawSelection->GetDragRect(tempRect);
  516.     fUpdateOffset = tempRect.TopLeft();
  517.  
  518.     // Before deleting the link destination shapes, clear the Undo stacks to get rid of
  519.     // any references to these doomed shapes.
  520.     ODUndo* undo = fPresentation->GetPart(ev)->GetSession(ev)->GetUndo(ev);
  521.     undo->ClearActionHistory(ev, kODDontRespectMarks);    // dis 'em
  522.  
  523.     // Delete the link destination shapes; they'll be recreated when the link is updated
  524.     fDrawSelection->DeleteSelection(ev);
  525. }
  526.  
  527. //----------------------------------------------------------------------------------------
  528. //    CDrawSubscribeLink::RestoreDrawSelection
  529. //----------------------------------------------------------------------------------------
  530. void CDrawSubscribeLink::RestoreDrawSelection(Environment* ev)
  531. {
  532.     fDrawSelection->CloseSelection(ev);    // empty the selection
  533.  
  534.     // Add the saved shapes to the selection
  535.     FW_COrderedCollectionIterator iter(fSavedSelection);
  536.     for (CBaseShape* shape = (CBaseShape*)iter.First(); iter.IsNotComplete(); shape = (CBaseShape*)iter.Next())
  537.     {
  538.         fDrawSelection->AddToSelection(ev, shape, FALSE);
  539.     }
  540.     fSavedSelection = NULL;
  541. }
  542.  
  543. //----------------------------------------------------------------------------------------
  544. //    CDrawSubscribeLink::EmptyCollection
  545. //----------------------------------------------------------------------------------------
  546. void CDrawSubscribeLink::EmptyCollection(Environment* ev)
  547. {
  548.     if (fCollection)
  549.     {
  550.         fCollection->RemoveAll();
  551.     }
  552. }
  553.  
  554. //----------------------------------------------------------------------------------------
  555. //    CDrawSubscribeLink::BreakLink - Override
  556. //----------------------------------------------------------------------------------------
  557. void CDrawSubscribeLink::BreakLink(Environment* ev)
  558. {
  559.     FW_CSubscribeLink::BreakLink(ev);
  560.  
  561.     //--- Erase Link Borders ---
  562.     fPresentation->Invalidate(ev);    // force all frames to be redrawn
  563.  
  564.     //--- Change status of embedded frames ---
  565.     FW_COrderedCollectionIterator ite(fCollection);
  566.     for (CBaseShape* shape = (CBaseShape*)ite.First(); ite.IsNotComplete(); shape = (CBaseShape*)ite.Next())
  567.     {
  568.         if (shape->GetShapeType() == kProxyShape)
  569.             ((CProxyShape*)shape)->ChangeLinkStatus(ev, kODNotInLink);
  570.     }
  571. }
  572.  
  573. //----------------------------------------------------------------------------------------
  574. //    CDrawSubscribeLink::AddShape
  575. //----------------------------------------------------------------------------------------
  576. void CDrawSubscribeLink::AddShape(Environment* ev, CBaseShape* shape)
  577. {
  578.     shape->SetSubscribeLink(ev, this);
  579.     if (fCollection == NULL)
  580.         fCollection = new FW_CPrivOrderedCollection;
  581.     fCollection->AddLast(shape);
  582. }
  583.  
  584. //----------------------------------------------------------------------------------------
  585. //    CDrawSubscribeLink::Externalize
  586. //----------------------------------------------------------------------------------------
  587.  
  588. void CDrawSubscribeLink::Externalize(Environment* ev, ODStorageUnit* storageUnit,
  589.                                      FW_CCloneInfo* cloneInfo)
  590. {
  591.     //-- Storage unit must be focused to property kDrawPropDestLink, value drawPartValueType
  592.     fODLink->Externalize(ev);
  593.  
  594.     ODID linkID = fODLink->GetID(ev);
  595.     if (cloneInfo != NULL)
  596.     {
  597.         linkID = cloneInfo->Clone(ev, linkID, 0, 0);
  598.     }
  599.     FW_ASSERT(linkID != kODNULL);
  600.  
  601.     //--- Write a reference to the link ---
  602.     ODStorageUnitRef suRef;
  603.     storageUnit->GetStrongStorageUnitRef(ev, linkID, suRef);
  604.     FW_CByteArray byteArray(&suRef, sizeof(ODStorageUnitRef));
  605.     storageUnit->SetValue(ev, byteArray);
  606.  
  607.     //--- Write link info ---
  608.     ODType kind = fLinkInfo.kind;                            // save kind string
  609.     fLinkInfo.kind = (ODType) strlen(kind) + 1;                // stash its length in linkInfo
  610.     byteArray.Set(&fLinkInfo, sizeof(ODLinkInfo));
  611.     storageUnit->SetValue(ev, byteArray);                    // write out linkInfo
  612.     byteArray.Set((void*)kind, (ODULong)fLinkInfo.kind);
  613.     storageUnit->SetValue(ev, byteArray);                    // write out kind string
  614.     fLinkInfo.kind = kind;                                    // restore kind string
  615.  
  616.     //--- Write the number of shapes in the link ---
  617.     unsigned long shapeCount = fCollection->Count();
  618.     FW_ASSERT(shapeCount != 0);
  619.     byteArray.Set(&shapeCount, sizeof(unsigned long));
  620.     storageUnit->SetValue(ev, byteArray);
  621.  
  622.     //--- Write the export index for each shape in the link ---
  623.     FW_COrderedCollectionIterator iter(fCollection);
  624.     for (CBaseShape* shape = (CBaseShape*)iter.First(); iter.IsNotComplete(); shape = (CBaseShape*)iter.Next())
  625.     {
  626.         short extIndex = shape->GetExternalizationIndex();
  627.         byteArray.Set(&extIndex, sizeof(short));
  628.         storageUnit->SetValue(ev, byteArray);
  629.     }
  630. }
  631.  
  632. //========================================================================================
  633. //    class CDrawLinkManager
  634. //========================================================================================
  635.  
  636. FW_DEFINE_CLASS_M1(CDrawLinkManager, FW_CLinkManager)
  637.  
  638. //----------------------------------------------------------------------------------------
  639. //    CDrawLinkManager constructor
  640. //----------------------------------------------------------------------------------------
  641.  
  642. CDrawLinkManager::CDrawLinkManager(Environment* ev, CDrawPart* thePart) :
  643.     FW_CLinkManager(ev, (FW_CPart*)thePart),
  644.     fDrawPart(thePart)
  645. {
  646. }
  647.  
  648. //----------------------------------------------------------------------------------------
  649. //    CDrawLinkManager destructor
  650. //----------------------------------------------------------------------------------------
  651.  
  652. CDrawLinkManager::~CDrawLinkManager()
  653. {
  654. }
  655.  
  656. //----------------------------------------------------------------------------------------
  657. //    CDrawLinkManager::NewPublishLink - Override
  658. //----------------------------------------------------------------------------------------
  659.  
  660. FW_CPublishLink* CDrawLinkManager::NewPublishLink(Environment* ev, ODUpdateID changeID, 
  661.                                                   FW_CPresentation* presentation)
  662. {
  663.     return new CDrawPublishLink(ev, changeID, 
  664.                                 presentation, fDrawPart->fDrawSelection, 
  665.                                 TRUE);    // saveSelection = TRUE
  666. }
  667.  
  668. //----------------------------------------------------------------------------------------
  669. //    CDrawLinkManager::NewSubscribeLink - Override
  670. //----------------------------------------------------------------------------------------
  671.  
  672. FW_CSubscribeLink* CDrawLinkManager::NewSubscribeLink(Environment* ev, ODLink *odLink,
  673.                                                       ODLinkInfo* linkInfo,
  674.                                                       FW_CPresentation* presentation)
  675. {
  676.     return new CDrawSubscribeLink(ev, odLink, presentation, fDrawPart->fDrawSelection, linkInfo);
  677. }
  678.  
  679. //----------------------------------------------------------------------------------------
  680. //    CDrawLinkManager::DoChangeLinkStatus - Override
  681. //----------------------------------------------------------------------------------------
  682.  
  683. void CDrawLinkManager::DoChangeLinkStatus(Environment* ev, ODFrame* odFrame)
  684. {
  685.     // call ODFrame::ChangeLinkStatus on any embedded frames that are involved in a link
  686.     // when a link is created, broken, moved, etc.
  687.     // odFrame is the frame of this part whose link status has changed.
  688.     
  689.     FW_CEmbeddingFrame* frame = FW_CEmbeddingFrame::ODtoFWEmbeddingFrame(ev, odFrame);
  690.     if (frame)
  691.     {
  692.         ODLinkStatus linkStatus = odFrame->GetLinkStatus(ev);
  693.  
  694.         // Only need to propagate linkStatus to embedded frames that don't participate in
  695.         // any of this part's links; otherwise their local link status takes precedence.
  696.  
  697.         FW_COrderedCollectionIterator iter(fDrawPart->GetShapeList());
  698.         for (CBaseShape* shape = (CBaseShape*)iter.First(); iter.IsNotComplete(); shape = (CBaseShape*)iter.Next())
  699.         {
  700.             if (shape->GetShapeType() == kProxyShape)
  701.             {
  702.                 CProxyShape* proxyShape = (CProxyShape*)shape;
  703.                 if (!proxyShape->IsPublished() && !proxyShape->IsSubscribed())
  704.                 {
  705.                     FW_CProxyEmbeddedFrameIterator efiter(ev, proxyShape);
  706.                     for (ODFrame* embFrame = efiter.First(ev); efiter.IsNotComplete(ev); embFrame = efiter.Next(ev))
  707.                         embFrame->ChangeLinkStatus(ev, linkStatus);
  708.                 }
  709.             }
  710.         }
  711.     }
  712. }
  713.  
  714. //----------------------------------------------------------------------------------------
  715. //    CDrawLinkManager::DoUpdateLinks - Override
  716. //----------------------------------------------------------------------------------------
  717.  
  718. void CDrawLinkManager::DoUpdateLinks(Environment* ev, ODFrame* odEmbeddedFrame, ODUpdateID change)
  719. {
  720.     // Content displayed in the embedded frame has changed
  721.  
  722.     /* 1) If odEmbeddedFrame is involved in one of my link sources, update the link with new data.
  723.           "If the part maintains the source of a link that includes the embedded frame, the
  724.           part should update the link." (Recipe p.12) */
  725.     if (this->CountPublishers(ev) > 0)
  726.     {
  727.         FW_CPartPublishIterator iter(fPart);
  728.         for (CDrawPublishLink* publisher = (CDrawPublishLink*)iter.First(); iter.IsNotComplete(); 
  729.                 publisher = (CDrawPublishLink*)iter.Next())
  730.         {
  731.             if (publisher->HasEmbeddedFrame(ev, odEmbeddedFrame))
  732.             {
  733.                 publisher->ContentUpdated(ev, change, FALSE);
  734.                 break;
  735.             }
  736.         }
  737.     }
  738.  
  739.     /* 2) Call ContentUpdated on my display frames as appropriate */
  740.     FW_CPartFrameIterator ite(fPart);
  741.     for (FW_CFrame* frame = ite.First(); ite.IsNotComplete(); frame = ite.Next())
  742.     {
  743.         frame->GetODFrame(ev)->ContentUpdated(ev, change);
  744.     }
  745. }
  746.  
  747. //----------------------------------------------------------------------------------------
  748. //    CDrawLinkManager::CreateLink - Override
  749. //----------------------------------------------------------------------------------------
  750. ODLinkSource* CDrawLinkManager::CreateLink(Environment *ev, ODByteArray* data)
  751. {
  752.     // CreateLink is overridden so that we can delete the pending publish link.
  753.     // This prevents the link spec from being re-used to create more than one link.
  754.  
  755.     ODLinkSource* odLinkSource = FW_CLinkManager::CreateLink(ev, data);
  756.     this->DeletePendingPublish(ev);
  757.     return odLinkSource;
  758. }
  759.  
  760. //----------------------------------------------------------------------------------------
  761. //    CDrawLinkManager::UndoPasteAs
  762. //----------------------------------------------------------------------------------------
  763. void CDrawLinkManager::UndoPasteAs(Environment* ev, CDrawSubscribeLink* link)
  764. {
  765.     //--- Break the link ---
  766.     this->BreakSubscribeLink(ev, link);
  767.  
  768.     //--- Remove subscribed shapes from the document ---
  769.     this->DeleteSubscribedShapes(ev, link);
  770. }
  771.  
  772. //----------------------------------------------------------------------------------------
  773. //    CDrawLinkManager::RedoPasteAs
  774. //----------------------------------------------------------------------------------------
  775. void CDrawLinkManager::RedoPasteAs(Environment* ev, CDrawSubscribeLink* link)
  776. {
  777.     //-- Restore the broken link --
  778.     this->RestoreSubscribeLink(ev, link);
  779.  
  780.     // When the restored link is updated, new subscriber shapes will be created
  781. }
  782.  
  783. //----------------------------------------------------------------------------------------
  784. //    CDrawLinkManager::CommitUndone
  785. //----------------------------------------------------------------------------------------
  786. void CDrawLinkManager::CommitUndone(Environment* ev, CDrawSubscribeLink* link)
  787. {
  788.     this->DeleteSubscribedShapes(ev, link);
  789.     delete link;
  790. }
  791.  
  792. //----------------------------------------------------------------------------------------
  793. //    CDrawLinkManager::DeleteSubscribedShapes
  794. //----------------------------------------------------------------------------------------
  795. void CDrawLinkManager::DeleteSubscribedShapes(Environment* ev, CDrawSubscribeLink* link)
  796. {
  797.     this->SelectSubscribedShapes(ev, link);
  798.     fDrawPart->fDrawSelection->DeleteSelection(ev);
  799.     link->EmptyCollection(ev);
  800. }
  801.  
  802. //----------------------------------------------------------------------------------------
  803. //    CDrawLinkManager::SelectSubscribedShapes
  804. //----------------------------------------------------------------------------------------
  805. void CDrawLinkManager::SelectSubscribedShapes(Environment* ev, CDrawSubscribeLink* link)
  806. {
  807.     fDrawPart->fDrawSelection->CloseSelection(ev);    // empty the selection
  808.  
  809.     // Saved link contains a list of the subscribed shapes
  810.     FW_COrderedCollectionIterator iter(link->fCollection); /* PRIVATE */
  811.     for (CBaseShape* shape = (CBaseShape*)iter.First(); iter.IsNotComplete(); shape = (CBaseShape*)iter.Next())
  812.     {
  813.         fDrawPart->fDrawSelection->AddToSelection(ev, shape, FALSE);
  814.     }
  815. }
  816.  
  817. //----------------------------------------------------------------------------------------
  818. //    CDrawLinkManager::GetLatestSubscriber
  819. //----------------------------------------------------------------------------------------
  820. CDrawSubscribeLink* CDrawLinkManager::GetLatestSubscriber(Environment* ev)
  821. {
  822.     // Return the most recent subscriber
  823.     FW_CPartSubscribeIterator iter(fPart);
  824.     return (CDrawSubscribeLink*) iter.Last();
  825. }
  826.  
  827. //----------------------------------------------------------------------------------------
  828. //    CDrawLinkManager::RevealLink - Override
  829. //----------------------------------------------------------------------------------------
  830. void CDrawLinkManager::RevealLink(Environment *ev, ODLinkSource* linkSource)
  831. {
  832.     CDrawPublishLink* sourceLink = (CDrawPublishLink*) ODtoPublishLink(ev, linkSource);
  833.     if (sourceLink == NULL) return;    // not our link!?
  834.  
  835.     // Choose a display frame for the source content
  836.     FW_CFrame* frame = sourceLink->GetFrameToRevealLink(ev);
  837.     if (frame)
  838.     {
  839.         // Ensure the display frame is revealed
  840.         if (!frame->GetWindow(ev)->IsActive(ev))
  841.             frame->GetWindow(ev)->Select(ev);        
  842.     
  843.         // ----- Activate the frame -----
  844.         if (!frame->IsActive(ev))
  845.         {
  846.             FW_CFrameFacetIterator iter(ev, frame);    // find a facet
  847.             frame->ActivateFrame(ev, iter.First(ev));
  848.         }
  849.  
  850.         // Select the shape(s) that make up this link source
  851.         sourceLink->DoSelect(ev, frame);
  852.     }
  853. }
  854.  
  855. //----------------------------------------------------------------------------------------
  856. //    CDrawLinkManager::ExternalizeLinks
  857. //----------------------------------------------------------------------------------------
  858.  
  859. void CDrawLinkManager::ExternalizeLinks(Environment* ev, ODStorageUnit* su,
  860.                                         FW_CCloneInfo* cloneInfo)
  861. {
  862.     ODValueType drawPartValueType = fDrawPart->GetPartKind(ev);
  863.  
  864.     //--- Write out the source links ---
  865.     if (this->CountPublishers(ev) > 0)
  866.     {
  867.         //-- Make sure the correct property and value is present in the SU --
  868.         FW_SUForceFocus(ev, su, kDrawPropSourceLink, drawPartValueType);
  869.  
  870.         FW_CPartPublishIterator iter(fPart);
  871.         for (CDrawPublishLink* slink = (CDrawPublishLink*)iter.First(); iter.IsNotComplete(); 
  872.                 slink = (CDrawPublishLink*)iter.Next())
  873.         {
  874.             slink->Externalize(ev, su, cloneInfo);
  875.         }
  876.     }
  877.     else
  878.         FW_SURemoveProperty(ev, su, kDrawPropSourceLink);
  879.  
  880.     //--- Write out the destination links ---
  881.     if (this->CountSubscribers(ev) > 0)
  882.     {
  883.         //-- Make sure the correct property and value is present in the SU --
  884.         FW_SUForceFocus(ev, su, kDrawPropDestLink, drawPartValueType);
  885.  
  886.         FW_CPartSubscribeIterator iter(fPart);
  887.         for (CDrawSubscribeLink* link = (CDrawSubscribeLink*)iter.First(); iter.IsNotComplete(); 
  888.                 link = (CDrawSubscribeLink*)iter.Next())
  889.         {
  890.             link->Externalize(ev, su, cloneInfo);
  891.         }
  892.     }
  893.     else
  894.         FW_SURemoveProperty(ev, su, kDrawPropDestLink);
  895. }
  896.  
  897. //----------------------------------------------------------------------------------------
  898. //    CDrawLinkManager::InternalizeLinks
  899. //----------------------------------------------------------------------------------------
  900.  
  901. void CDrawLinkManager::InternalizeLinks(Environment* ev, ODStorageUnit* storageUnit)
  902. {
  903.     ODValueType drawPartValueType = fDrawPart->GetPartKind(ev);
  904.     unsigned long valueSize;
  905.  
  906.     if (storageUnit->Exists(ev, kDrawPropSourceLink, kODNULL, kODNULL))
  907.     {
  908.         storageUnit->Focus(ev, kDrawPropSourceLink, kODPosUndefined, drawPartValueType, 0, kODPosUndefined);
  909.         valueSize = storageUnit->GetSize(ev);
  910.         while (storageUnit->GetOffset(ev) < valueSize)
  911.         {
  912.             this->InternalizeOneSourceLink(ev, storageUnit);
  913.         }
  914.     }
  915.  
  916.     if (storageUnit->Exists(ev, kDrawPropDestLink, kODNULL, kODNULL))
  917.     {
  918.         storageUnit->Focus(ev, kDrawPropDestLink, kODPosUndefined, drawPartValueType, 0, kODPosUndefined);
  919.         valueSize = storageUnit->GetSize(ev);
  920.         while (storageUnit->GetOffset(ev) < valueSize)
  921.         {
  922.             this->InternalizeOneDestLink(ev, storageUnit);
  923.         }
  924.     }
  925. }
  926.  
  927. //----------------------------------------------------------------------------------------
  928. //    CDrawLinkManager::GetSUValue
  929. //----------------------------------------------------------------------------------------
  930.  
  931. ODULong CDrawLinkManager::GetSUValue(Environment* ev, ODStorageUnit* su, 
  932.                                      unsigned long size, void *buffer)
  933. {
  934.     // Convenience function; also makes code easier to read
  935.     FW_CByteArray ba;
  936.     ODULong bytesRead = su->GetValue(ev, size, ba);
  937.     ba.CopyBuffer(buffer, bytesRead);
  938.     
  939.     return bytesRead;
  940. }
  941.  
  942. //----------------------------------------------------------------------------------------
  943. //    CDrawLinkManager::InternalizeOneDestLink
  944. //----------------------------------------------------------------------------------------
  945.  
  946. void CDrawLinkManager::InternalizeOneDestLink(Environment* ev, ODStorageUnit* storageUnit)
  947. {
  948.     //-- Storage unit must be focused to property kDrawPropDestLink, value drawPart kind
  949.     ODStorageUnitRef suRef;
  950.     ODLinkInfo linkInfo;
  951.     ODDraft* suDraft = storageUnit->GetDraft(ev);
  952.  
  953.     GetSUValue(ev, storageUnit, kODStorageUnitRefSize, &suRef);
  954.     if (storageUnit->IsValidStorageUnitRef(ev, suRef))
  955.     {
  956.         // We have a validated SU ref for the link, so read the link data
  957.         ODLink* odLink = suDraft->AcquireLink(ev, storageUnit->GetIDFromStorageUnitRef(ev, suRef), NULL);
  958.  
  959.         //--- Read the link info and kind ---
  960.         GetSUValue(ev, storageUnit, sizeof(ODLinkInfo), &linkInfo);
  961.         // the length of the kind string was saved in the kind field
  962.         ODType kind = (ODType) FW_CMemoryManager::AllocateBlock((ODULong)linkInfo.kind);
  963.         GetSUValue(ev, storageUnit, (ODULong)linkInfo.kind, (void*)kind);    // read the kind string
  964.         linkInfo.kind = kind;
  965.  
  966.         //--- Create a subscriber object for this link ---
  967.         CDrawSubscribeLink* destLink = new CDrawSubscribeLink(ev, odLink, fDrawPart->GetMainPresentation(), fDrawPart->fDrawSelection, &linkInfo);
  968.  
  969.         //--- Read the number of shapes in the link ---
  970.         unsigned long shapeCount;
  971.         GetSUValue(ev, storageUnit, sizeof(unsigned long), &shapeCount);
  972.  
  973.         //--- Read each shape index and add the shape to the source link ---
  974.         short extIndex;
  975.         while (shapeCount > 0)
  976.         {
  977.             GetSUValue(ev, storageUnit, sizeof(short), &extIndex);
  978.             CBaseShape* shape = fDrawPart->FindShapeWithIndex(extIndex);
  979.             if (shape)
  980.                 destLink->AddShape(ev, shape);
  981.             shapeCount--;
  982.         }
  983.  
  984.         //--- Finish subscribing ---
  985.         this->AddToSubscribeLinkList(ev, destLink);
  986.         destLink->HandleSubscribe(ev);
  987.         odLink->Release(ev);    // to balance AcquireLink above
  988.     }
  989. }
  990.  
  991. //----------------------------------------------------------------------------------------
  992. //    CDrawLinkManager::InternalizeOneSourceLink
  993. //----------------------------------------------------------------------------------------
  994.  
  995. void CDrawLinkManager::InternalizeOneSourceLink(Environment* ev, ODStorageUnit* storageUnit)
  996. {
  997.     //-- Storage unit must be focused to property kDrawPropSourceLink, value drawPart kind
  998.     ODStorageUnitRef suRef;
  999.     ODUpdateID updateID;
  1000.     ODDraft* suDraft = storageUnit->GetDraft(ev);
  1001.  
  1002.     GetSUValue(ev, storageUnit, kODStorageUnitRefSize, &suRef);
  1003.     if (storageUnit->IsValidStorageUnitRef(ev, suRef))
  1004.     {
  1005.         // We have a validated SU ref for the link, so read the link source data
  1006.         ODLinkSource* odLinkSource = suDraft->AcquireLinkSource(ev, storageUnit->GetIDFromStorageUnitRef(ev, suRef));
  1007.         GetSUValue(ev, storageUnit, sizeof(ODUpdateID), &updateID);
  1008.  
  1009.         //--- Create a publish object for this source link ---
  1010.         CDrawPublishLink* sourceLink = new CDrawPublishLink(ev, updateID, fDrawPart->GetMainPresentation(), fDrawPart->fDrawSelection, FALSE);
  1011.  
  1012.         //--- Read the number of shapes in the link ---
  1013.         unsigned long shapeCount;
  1014.         GetSUValue(ev, storageUnit, sizeof(unsigned long), &shapeCount);
  1015.  
  1016.         //--- Read each shape index and add the shape to the source link ---
  1017.         short extIndex;
  1018.         while (shapeCount > 0)
  1019.         {
  1020.             GetSUValue(ev, storageUnit, sizeof(short), &extIndex);
  1021.             CBaseShape* shape = fDrawPart->FindShapeWithIndex(extIndex);
  1022.             if (shape)
  1023.                 sourceLink->AddShape(ev, shape);
  1024.             shapeCount--;
  1025.         }
  1026.  
  1027.         //--- Make this publisher official ---
  1028.         sourceLink->SetODLinkSource(ev, odLinkSource);
  1029.         this->AddToPublishLinkList(ev, sourceLink);
  1030.         odLinkSource->Release(ev);    // to balance AcquireLinkSource above
  1031.     }
  1032. }
  1033.  
  1034. //----------------------------------------------------------------------------------------
  1035. //    CDrawLinkManager::RegisterSubscribers
  1036. //----------------------------------------------------------------------------------------
  1037. void CDrawLinkManager::RegisterSubscribers(Environment* ev)
  1038. {
  1039.     if (this->CountSubscribers(ev) > 0)
  1040.     {
  1041.         FW_CPartSubscribeIterator iter(fPart);
  1042.         for (CDrawSubscribeLink* link = (CDrawSubscribeLink*)iter.First(); iter.IsNotComplete(); link = (CDrawSubscribeLink*)iter.Next())
  1043.         {
  1044.             link->Register(ev, fPart);    // auto-update link will have its LinkUpdated method called
  1045.         }
  1046.     }
  1047. }
  1048.